package view;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;

import javax.swing.JOptionPane;


public class CalculatorParser {

	private static String sNumbers = "0123456789";
	private static String sDot = ".";
	private static String sOperators = "+-/*";

	//counts number of math symbols occurrences
	//except '-' if it is first sign of inputString
	public static int countOperators(String inputString) {
		int counter = 0;

		if (inputString != null && inputString.length() > 0) {
			if (inputString.charAt(0) == '-') {
				if (inputString.length() > 1) {
					inputString = inputString.substring(1);
				} else {
					return 0;
				}
			}
			String[] searchedSymbols = { "+", "-", "*", "/" };

			for (String symbol : searchedSymbols) {
				String helpString = inputString;

				while (helpString.contains(symbol)) {
					counter++;
					helpString = helpString.substring(helpString
							.indexOf(symbol) + 1);
				}
			}
		}
		return counter;
	}

	//counts number of dot occurences
	public static int countDots(String inputString) {
		int counter = 0;

		if (inputString != null) {

			while (inputString.contains(sDot)) {
				counter++;
				inputString = inputString
						.substring(inputString.indexOf(sDot) + 1);
			}
		}
		return counter;
	}

	//returns operation symbol
	public static char getOperation(String inputString) {
		String[] searchedSymbols = { "+", "-", "*", "/" };
		char c = 0;

		if (inputString != null) {
			if (inputString.length() > 0 && inputString.charAt(0) == '-') {
				inputString = inputString.substring(1);
			}

			if (countOperators(inputString) == 1) {
				for (String symbol : searchedSymbols) {
					if (inputString.contains(symbol)) {
						c = symbol.charAt(0);
					}
				}
			}
		}
		return c;
	}

	public static OperationElements parseInput(String inputString) {

		char operator = 0;
		String[] numStrings = new String[2];
		double[] numbers = new double[2];

		if (countOperators(inputString) == 1) {
			operator = getOperation(inputString);
			int indexOfOperator = inputString.indexOf(Character
					.toString(operator));
			
			numStrings[0] = inputString.substring(0, indexOfOperator);
			numbers[0] = Double.parseDouble(numStrings[0]);

			if ((indexOfOperator + 1) == inputString.length()) {
				numbers[1] = numbers[0];
			} else {
				numStrings[1] = inputString.substring(indexOfOperator + 1);
				numbers[1] = Double.parseDouble(numStrings[1]);
			}

		} else if (countOperators(inputString) == 0) {
			numbers[0] = Double.parseDouble(inputString);
		}

		return new OperationElements(numbers[0], numbers[1], operator);

	}

	public static String parseOnTheGo(String currentString, String nextSign) {

		if (currentString.length() == 0) {
			String allowedAsFirst = sNumbers + "-";
			if (allowedAsFirst.contains(nextSign)) {
				return nextSign;
			} else {
				return "";
			}
		} else {
			int countOps = countOperators(currentString);
			switch (countOps) {
			case 0:
				if (sNumbers.contains(nextSign)) {
					return currentString + nextSign;
				} else if (sOperators.contains(nextSign)) {
					String lastSign = Character.toString(currentString
							.charAt(currentString.length() - 1));
					if (".-".contains(lastSign)) {
						return currentString;
					} else {
						return currentString + nextSign;
					}
				} else if (sDot.contains(nextSign)) {

					if (countDots(currentString) > 0) {
						return currentString;
					} else {
						return currentString + nextSign;
					}
				} else if (nextSign.equals("000")) {
					return currentString + nextSign;
				} else {
					return currentString;
				}
			case 1:
				if (sNumbers.contains(nextSign)) {
					return currentString + nextSign;
				} else if (sDot.contains(nextSign)) {
					if (sOperators.contains(currentString
							.substring(currentString.length() - 1))) {
						return currentString;
					} else {
						String operation = Character
								.toString(getOperation(currentString));
						int opIndex = currentString.substring(1).indexOf(
								operation) + 1;
						int dots = countDots(currentString.substring(opIndex));
						if (dots > 0) {
							return currentString;
						} else {
							return currentString + nextSign;
						}
					}
				} else if (nextSign.equals("000")) {
					return currentString + nextSign;
				} else {
					return currentString;
				} 
			default: // >1
				return currentString;
			}

		}

	}

	public static String performOperation(OperationElements opEl) {

		double result;

		switch (opEl.operator) {
		case '+':
			result = opEl.part1 + opEl.part2;
			break;
		case '-':
			result = opEl.part1 - opEl.part2;
			break;
		case '*':
			result = opEl.part1 * opEl.part2;
			break;
		case '/':
			result = opEl.part1 / opEl.part2;
			break;
		default:
			result = opEl.part1;
		}

		DecimalFormat df = new DecimalFormat("#.########");
		DecimalFormatSymbols custom = new DecimalFormatSymbols();
		custom.setDecimalSeparator('.');
		df.setDecimalFormatSymbols(custom);

		//handle division by zero
		if(Double.isInfinite(result)){
			JOptionPane.showMessageDialog(null, "Cannot divide by zero!");
			return "0";
		} else {
			return df.format(result);
		}
	
	}

}
